/*
 * @author Stanislovas Mickus
 * @version 5
 * @date 29 November, 2013
 *
 * Licensed under the GNU General Public License, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/copyleft/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.stasmobstudios.musicplayer.views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.stasmobstudios.musicplayer.R;
import com.stasmobstudios.musicplayer.activities.MusicPlayerUI;
import com.stasmobstudios.musicplayer.interfaces.PlaybackServiceInterface;
import com.stasmobstudios.musicplayer.viewgroups.StopSwipeViewPager;

/**
 * The Class CircularSeekBar.
 */
public class ClockSeekBar extends View {
    private StopSwipeViewPager mainStopSwipeViewPager;

    /**
     * More accurate (float) progress
     */
    private float exactPart;

    /**
     * The context
     */
    private Context mContext;

    /**
     * The listener to listen for changes
     */
    private OnSeekChangeListener mListener;

    /**
     * The width of the view
     */
    private int width;

    /**
     * The height of the view
     */
    private int height;

    /**
     * The maximum progress amount
     */
    private int maxProgress = 100;

    /**
     * The current progress
     */
    private int progress = 0;

    /**
     * The clock's center X coordinate
     */
    private float cx;

    /**
     * The Y coordinate for the current position of the progress.
     */
    private float markPointY = 0;

    /**
     * The clock progress bitmaps.
     */
    private Bitmap progressSand1, progressSand2, progressSand3, progressSand4, progressSand5, progressSand6, progressSand7, progressSand8, progressSand9, progressSand10, progressSand11;

    /**
     * The flag to see if view is pressed
     */
    private boolean IS_PRESSED = false;

    {
        mListener = new OnSeekChangeListener() {

            @Override
            public void onProgressChange(ClockSeekBar view, int newProgress) {

            }
        };
    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context  the context
     * @param attrs    the attrs
     * @param defStyle the def style
     */
    public ClockSeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        initDrawable();
    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context the context
     * @param attrs   the attrs
     */
    public ClockSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initDrawable();
    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context the context
     */
    public ClockSeekBar(Context context) {
        super(context);
        mContext = context;
        initDrawable();
    }

    /**
     * Inits the drawable.
     */
    public void initDrawable() {
        Log.d("ClockSeekBar", "Device size: " + getResources().getString(R.string.layout_density));
        BitmapFactory.Options options = new BitmapFactory.Options();
        progressSand1 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_1, options);
        progressSand2 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_2, options);
        progressSand3 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_3, options);
        progressSand4 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_4, options);
        progressSand5 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_5, options);
        progressSand6 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_6, options);
        progressSand7 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_7, options);
        progressSand8 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_8, options);
        progressSand9 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_9, options);
        progressSand10 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_10, options);
        progressSand11 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.smeliolaik_11, options);
    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec - getPaddingLeft() - getPaddingRight(), heightMeasureSpec - getPaddingTop() - getPaddingBottom());

        width = getWidth() - getPaddingLeft() - getPaddingRight(); // Get View Width
        height = getHeight() - getPaddingTop() - getPaddingBottom();// Get View Height
        cx = width / 2 + getPaddingLeft(); // Center X for circle
    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        int eleventhHeight = getHeight() / 11;
        int alpha = (int)( 255 * ( markPointY %  eleventhHeight ) / eleventhHeight);
        Paint secondLayerPaint = new Paint();
        secondLayerPaint.setAlpha(alpha);
        int level = (int) Math.floor(markPointY / eleventhHeight) + 1;
        level = (level == 12) ? 11 : level;
        switch ( level ) {
            case 1:
                canvas.drawBitmap(progressSand1, new Rect(0, 0, progressSand1.getWidth(), progressSand1.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand2, new Rect(0, 0, progressSand2.getWidth(), progressSand2.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 2:
                canvas.drawBitmap(progressSand2, new Rect(0, 0, progressSand2.getWidth(), progressSand2.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand3, new Rect(0, 0, progressSand3.getWidth(), progressSand3.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 3:
                canvas.drawBitmap(progressSand3, new Rect(0, 0, progressSand3.getWidth(), progressSand3.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand4, new Rect(0, 0, progressSand4.getWidth(), progressSand4.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 4:
                canvas.drawBitmap(progressSand4, new Rect(0, 0, progressSand4.getWidth(), progressSand4.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand5, new Rect(0, 0, progressSand5.getWidth(), progressSand5.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 5:
                canvas.drawBitmap(progressSand5, new Rect(0, 0, progressSand5.getWidth(), progressSand5.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand6, new Rect(0, 0, progressSand6.getWidth(), progressSand6.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 6:
                canvas.drawBitmap(progressSand6, new Rect(0, 0, progressSand6.getWidth(), progressSand6.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand7, new Rect(0, 0, progressSand7.getWidth(), progressSand7.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 7:
                canvas.drawBitmap(progressSand7, new Rect(0, 0, progressSand7.getWidth(), progressSand7.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand8, new Rect(0, 0, progressSand8.getWidth(), progressSand8.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 8:
                canvas.drawBitmap(progressSand8, new Rect(0, 0, progressSand8.getWidth(), progressSand8.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand9, new Rect(0, 0, progressSand9.getWidth(), progressSand9.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 9:
                canvas.drawBitmap(progressSand9, new Rect(0, 0, progressSand9.getWidth(), progressSand9.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand10, new Rect(0, 0, progressSand10.getWidth(), progressSand10.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 10:
                canvas.drawBitmap(progressSand10, new Rect(0, 0, progressSand10.getWidth(), progressSand10.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                canvas.drawBitmap(progressSand11, new Rect(0, 0, progressSand11.getWidth(), progressSand11.getHeight()), new Rect(0, 0, getWidth(), getHeight()), secondLayerPaint);
                break;
            case 11:
                canvas.drawBitmap(progressSand11, new Rect(0, 0, progressSand11.getWidth(), progressSand11.getHeight()), new Rect(0, 0, getWidth(), getHeight()), null);
                break;
        }

        super.onDraw(canvas);
    }

    /**
     * Sets the seek bar change listener.
     *
     * @param listener the new seek bar change listener
     */
    public void setSeekBarChangeListener(OnSeekChangeListener listener) {
        mListener = listener;
    }

    /**
     * Gets the seek bar change listener.
     *
     * @return the seek bar change listener
     */
    public OnSeekChangeListener getSeekBarChangeListener() {
        return mListener;
    }

    /**
     * The listener interface for receiving onSeekChange events. The class that
     * is interested in processing a onSeekChange event implements this
     * interface, and the object created with that class is registered with a
     * component using the component's
     * <code>setSeekBarChangeListener(OnSeekChangeListener)<code> method. When
     * the onSeekChange event occurs, that object's appropriate
     * method is invoked.
     *
     * @see //OnSeekChangeEvent
     */
    public interface OnSeekChangeListener {

        /**
         * On progress change.
         *
         * @param view        the view
         * @param newProgress the new progress
         */
        public void onProgressChange(ClockSeekBar view, int newProgress);
    }

    /**
     * Gets the max progress.
     *
     * @return the max progress
     */
    public int getMaxProgress() {
        return maxProgress;
    }

    /**
     * Sets the max progress.
     *
     * @param maxProgress the new max progress
     */
    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    /**
     * Gets the progress.
     *
     * @return the progress
     */
    public int getProgress() {
        return progress;
    }

    /**
     * Sets the progress.
     *
     * @param progress the new progress
     */
    public void setProgress(int progress) {
        if (this.progress != progress) {
            this.progress = progress;
            mListener.onProgressChange(this, this.getProgress());
            invalidate();
        }
    }

    public void refreshClockProgress(int progress) {
        if (this.progress != progress) {
            this.progress = progress;
            markPointY = (progress * getHeight()) / 100;
            invalidate();
        }
    }

    public void refreshCanvasProgress(float exactPart) {
        if (this.exactPart != exactPart) {
            this.exactPart = exactPart;
            this.progress = (int) exactPart * 100;
            markPointY = exactPart * getHeight();
            invalidate();
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //Don't handle until PlaybackService initialized track
        PlaybackServiceInterface playbackService = MusicPlayerUI.getMusicPlayerActivity().getPlaybackSrevice();
        if (playbackService == null || !playbackService.isPrepared()) return true;

        float x = event.getX();
        float y = event.getY();
        boolean up = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                moved(x, y, up);
                mainStopSwipeViewPager.setLockEnabled(true);
                break;
            case MotionEvent.ACTION_MOVE:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_UP:
                up = true;
                moved(x, y, up);
                mainStopSwipeViewPager.setLockEnabled(false);
                break;
        }
        return true;
    }

    /**
     * Moved.
     *
     * @param x  the x
     * @param y  the y
     * @param up the up
     */
    private void moved(float x, float y, boolean up) {
        if ( y > 0 && y < getHeight() ) {
            IS_PRESSED = true;
            markPointY = y;

            int procents = (int) (markPointY / getHeight() * 100);
            setProgress(procents);
            invalidate();

        } else {
            IS_PRESSED = false;
            invalidate();
        }
    }

    /**
     * Moved.
     *
     * @param ssvp  the stop swipe ViewPager setter
     */
    public void setStopSwipeViewPager(StopSwipeViewPager ssvp) {
        mainStopSwipeViewPager = ssvp;
    }

    @Override
    protected void onDetachedFromWindow() {
        progressSand1.recycle();
        progressSand2.recycle();
        progressSand3.recycle();
        progressSand4.recycle();
        progressSand5.recycle();
        progressSand6.recycle();
        progressSand7.recycle();
        progressSand8.recycle();
        progressSand9.recycle();
        progressSand10.recycle();
        progressSand11.recycle();
    }
}
